/*
 *    Copyright (c) 2018-2025, lengleng All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the pig4cloud.com developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: lengleng (wangiegie@gmail.com)
 */
package com.pig4cloud.pig.juhe.admin.service.impl;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dy.yunying.api.entity.ParentGameVersionDO;
import com.dy.yunying.api.feign.RemotePGameService;
import com.pig4cloud.pig.admin.api.dto.UserInfo;
import com.pig4cloud.pig.admin.api.entity.SysUser;
import com.pig4cloud.pig.admin.api.feign.RemoteUserService;
import com.pig4cloud.pig.common.core.constant.SecurityConstants;
import com.pig4cloud.pig.common.core.util.R;
import com.pig4cloud.pig.common.security.util.SecurityUtils;
import com.pig4cloud.pig.juhe.admin.config.JuheProperties;
import com.pig4cloud.pig.juhe.admin.mapper.JuheChannelAttrValueMapper;
import com.pig4cloud.pig.juhe.admin.mapper.JuheChannelInfoMapper;
import com.pig4cloud.pig.juhe.admin.mapper.JuheGameChannelMapper;
import com.pig4cloud.pig.juhe.admin.mapper.JuheGameInfoMapper;
import com.pig4cloud.pig.juhe.admin.mapper.JuheGamePageMapper;
import com.pig4cloud.pig.juhe.admin.mapper.JuhePackMapper;
import com.pig4cloud.pig.juhe.admin.service.AsyncService;
import com.pig4cloud.pig.juhe.admin.service.JuhePackService;
import com.pig4cloud.pig.juhe.api.entity.JuheChannelInfo;
import com.pig4cloud.pig.juhe.api.entity.JuheGameChannel;
import com.pig4cloud.pig.juhe.api.entity.JuheGameInfo;
import com.pig4cloud.pig.juhe.api.entity.JuheGamePage;
import com.pig4cloud.pig.juhe.api.entity.JuhePack;
import com.pig4cloud.pig.juhe.api.request.JuhePackageRequest;
import com.pig4cloud.pig.juhe.api.request.PushPackageRequest;
import com.pig4cloud.pig.juhe.api.util.Constant;
import com.pig4cloud.pig.juhe.api.util.HttpUtils;
import com.pig4cloud.pig.juhe.api.util.PythonUtil;
import com.pig4cloud.pig.juhe.api.util.ScpUtil;
import com.pig4cloud.pig.juhe.api.vo.AsyncPackInfoData;
import com.pig4cloud.pig.juhe.api.vo.JuheChannelAttrValueVo;
import com.pig4cloud.pig.juhe.api.vo.JuhePackVo;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 聚合打包记录表
 *
 * @author yuwenfeng
 * @date 2021-09-15 13:47:28
 */
@Service
@AllArgsConstructor
@Slf4j
public class JuhePackServiceImpl extends ServiceImpl<JuhePackMapper, JuhePack> implements JuhePackService {

	private final JuheChannelAttrValueMapper juheChannelAttrValueMapper;

	private final JuheGamePageMapper juheGamePageMapper;

	private final JuheChannelInfoMapper juheChannelInfoMapper;

	private final JuheGameChannelMapper juheGameChannelMapper;

	private final JuheGameInfoMapper juheGameInfoMapper;

	private final RemoteUserService remoteUserService;

	private final AsyncService asyncService;

	private final JuheProperties juheProperties;

	private final RemotePGameService remoteParentGameService;

	@Override
	public Page<JuhePackVo> selectJuhePackVoPage(Page<JuhePack> page, QueryWrapper<JuhePack> query) {
		return baseMapper.selectJuhePackVoPage(page, query);
	}

	@Override
	public List<JuheChannelAttrValueVo> selectAttrValueList(Long channelId, Long gameId) {
		return juheChannelAttrValueMapper.selectAttrValueVoList(channelId, gameId);
	}

	@Override
	public R juhePackage(JuhePackageRequest request) {
		SysUser sysUser = null;
		R<UserInfo> userInfo = remoteUserService.findUserByUserId(SecurityUtils.getUser().getId(), SecurityConstants.FROM_IN);
		if (null != userInfo.getData()) {
			sysUser = userInfo.getData().getSysUser();
		}
		if (null == sysUser) {
			return R.failed("无法获取登录账号信息");
		}
		JuheGameInfo gameInfo = juheGameInfoMapper.selectOne(new QueryWrapper<JuheGameInfo>().eq("game_id", request.getGameId()).eq("del_flag", Constant.DEL_NO));
		if (null == gameInfo) {
			return R.failed("游戏不存在");
		}
		JuheGamePage gamePage = juheGamePageMapper.selectOne(new QueryWrapper<JuheGamePage>().eq("page_id", request.getPageId()).eq("game_id", gameInfo.getGameId()).eq("page_status", Constant.PAGE_STATUS_SUCC));
		if (null == gamePage) {
			return R.failed("母包获取失败");
		}
		String[] channelIds = request.getChannelIds().split(",");
		if (channelIds.length > 0) {
			List<JuheChannelAttrValueVo> attrValueList;
			JuheChannelInfo channelInfo;
			JuheGameChannel gameChannel;
			JuhePack info = null;
			//先生成打包记录
			List<AsyncPackInfoData> packDataList = new ArrayList<AsyncPackInfoData>();
			AsyncPackInfoData packData;
			for (String channelId : channelIds) {
				Long cId = Long.valueOf(channelId);
				gameChannel = juheGameChannelMapper.selectOne(new QueryWrapper<JuheGameChannel>().eq("channel_id", cId).eq("game_id", gameInfo.getGameId()).eq("del_flag", Constant.DEL_NO));
				if (null == gameChannel) {
					return R.failed("该游戏未配置该渠道");
				}
				attrValueList = juheChannelAttrValueMapper.selectAttrValueVoList(cId, gameInfo.getGameId());
				if (CollectionUtils.isEmpty(attrValueList)) {
					return R.failed("无法获取游戏渠道属性值");
				}
				channelInfo = juheChannelInfoMapper.selectById(cId);
				if (null == channelInfo) {
					return R.failed("渠道获取失败");
				}
				info = new JuhePack();
				info.setChannelId(cId);
				info.setGameId(gamePage.getGameId());
				info.setPageId(gamePage.getPageId());
				info.setPackVersion(gamePage.getPageVersion());
				info.setPackStatus(Constant.PACKAGE_STATUS_WAIT);
				info.setCreateBy(sysUser.getRealName());
				baseMapper.insert(info);
				packData = new AsyncPackInfoData();
				packData.setPackId(info.getPackId());
				packData.setAttrValueList(attrValueList);
				packData.setChannelInfo(channelInfo);
				packData.setGamePage(gamePage);
				packData.setGameInfo(gameInfo);
				packData.setGameChannel(gameChannel);
				packDataList.add(packData);
			}
			asyncService.packChannelApk(packDataList);
			return R.ok();
		} else {
			return R.failed("获取渠道集合失败");
		}
	}

	@Override
	public R<String> uploadFile(MultipartFile file) throws Exception {
		String extension = PythonUtil.getExtension(file);
		String filePath = "";
		if (Constant.APK.equalsIgnoreCase(extension) || Constant.IPA.equalsIgnoreCase(extension)) {
			filePath = Constant.FILE_PACKAGE_IN;
		} else {
			filePath = Constant.FILE_IMAGES_PATH;
		}
		// 自定义文件名
		String fileName = IdUtil.simpleUUID() + StrUtil.DOT + FileUtil.extName(file.getOriginalFilename());
		// 获取file对象
		File fileDesc = new File(juheProperties.getJuheFileDir() + filePath + File.separator + fileName);
		if (!fileDesc.getParentFile().exists()) {
			fileDesc.getParentFile().mkdirs();
		}
		// 写入file
		file.transferTo(fileDesc);
		return R.ok(juheProperties.getJuheFilePath() + filePath + StrUtil.SLASH + fileName);
	}

	@Override
	public List<JuheChannelInfo> selectChannelList(QueryWrapper<JuheChannelInfo> query) {
		return juheGameChannelMapper.selectChannelList(query);
	}

	@Override
	public R pushPackage(PushPackageRequest request) throws IOException {
		JuhePack juhePack = baseMapper.selectOne(new QueryWrapper<JuhePack>().eq("pack_id", request.getPackId()).eq("pack_status", Constant.PACKAGE_STATUS_SUCC));
		if (null == juhePack) {
			return R.failed("只能推送打包成功的母包");
		}
		File apkFile = new File(juhePack.getPackUrl().replace(juheProperties.getJuheFilePath(), juheProperties.getJuheFileDir()));
		String remotePackageDir = juheProperties.getJuheScpClientRemoteDir() + apkFile.getName();
		if (1 == juheProperties.getJuheApkPushType()) {
			Instant start = Instant.now();
			FileUtils.copyFile(apkFile, new File(remotePackageDir));
			Instant finish = Instant.now();
			long timeElapsed = Duration.between(start, finish).toMillis();
			log.info("pushPackage-copy文件消耗时长：{}", timeElapsed);
		} else {
			Instant start = Instant.now();
			String localPath = juhePack.getPackUrl().replace(juheProperties.getJuheFilePath(), juheProperties.getJuheFileDir());
			boolean uploadResult = ScpUtil.scpFile(juheProperties.getJuheScpClientIP(), juheProperties.getJuheScpClientName(), juheProperties.getJuheScpClientPassword(), juheProperties.getJuheScpClientPort(), localPath, juheProperties.getJuheScpClientRemoteDir());
			Instant finish = Instant.now();
			long timeElapsed = Duration.between(start, finish).toMillis();
			log.info("pushPackage-Scp传输文件消耗时长：{}", timeElapsed);
			if (!uploadResult) {
				return R.failed("Scp文件推送失败，请联系管理员");
			}
		}
		//1，调用读包接口
		Map<String, String> paramsMap = new HashMap<>();
		paramsMap.put("remotePackageDir", remotePackageDir);
		paramsMap.put("pkName", request.getPkName());
		paramsMap.put("parentGameId", request.getParentGameId().toString());
		if (null != request.getVersionCode()) {
			paramsMap.put("versionCode", request.getVersionCode().toString());
		}
		//超时时间设置最大值
		String result = HttpUtils.doPost(juheProperties.getJuheApkPushUrl(), paramsMap, Integer.MAX_VALUE, 5000);
		log.info("调用读包接口返回值：{}", result);
		if (StringUtils.isNotBlank(result)) {
			JSONObject resultJson = JSON.parseObject(result);
			if (null != resultJson) {
				if (null != resultJson.get("code") && 0 == resultJson.getIntValue("code")) {
					JSONObject dataJson = resultJson.getJSONObject("data");
					//2，新增母包记录接口
					ParentGameVersionDO addParams = new ParentGameVersionDO();
					addParams.setCode(dataJson.getIntValue("versionCode"));
					addParams.setContent(request.getContext());
					addParams.setFileName(dataJson.getString("fileName"));
					addParams.setGameId(request.getParentGameId());
					addParams.setName(dataJson.getString("versionName"));
					addParams.setPath(dataJson.getString("path"));
					addParams.setPkName(dataJson.getString("packageName"));
					addParams.setSize(dataJson.getString("size"));
					log.info("add接口参数addParams:{}", JSON.toJSONString(addParams));
					return remoteParentGameService.add(addParams);
				} else {
					return R.failed(resultJson.getString("msg"));
				}
			}
			return R.failed("读包服务响应错误");
		} else {
			return R.failed("运营分包服务无响应，请联系管理员");
		}
	}

}
